Skip to content

feat(GitClone): select an existing local checkout instead of cloning - #193

Merged
odgrim merged 1 commit into
mainfrom
feat/gitclone-local-checkout
Aug 21, 2026
Merged

feat(GitClone): select an existing local checkout instead of cloning#193
odgrim merged 1 commit into
mainfrom
feat/gitclone-local-checkout

Conversation

@odgrim

@odgrim odgrim commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

What

<GitClone> gets a repository-source picker: Clone from remote (unchanged) or Use local checkout.

┌─ Clone Repository ──────────────── [git_clone] ─┐
│ ( ) Clone from remote   (•) Use local checkout  │
│                                                 │
│ Repository directory                            │
│ [ /Users/me/dev/infra-live      ] [ Browse… ]   │
│ ✓ Git repository                                │
│   Root: /Users/me/dev/infra-live                │
│   Remote: https://github.com/acme/infra-live    │
│   On branch main · 428 tracked files            │
│                                                 │
│ [ Use This Repo ]                               │
└─────────────────────────────────────────────────┘

Why

Users often already have the repo — a long-lived infrastructure-live checkout, a work in progress branch, a monorepo nobody wants to re-download. Today the only way into a runbook is a fresh clone.

How it works

Picking a directory reads it only. The block resolves the work tree root with git rev-parse --show-toplevel (so any subdirectory of the checkout works), reads the origin remote and current branch, and counts tracked files. That runs as you type or browse, so a wrong directory says so immediately — nothing is fetched, pulled, or modified, and no credentials are needed.

Confirming with Use This Repo registers the checkout as a session worktree and emits the same outputs a clone does, so nothing downstream can tell the two apart: same clone_path / repo_owner / repo_name, same $REPO_FILES, same workspace file tree, same <GitPullRequest> flow — a PR opens against the checkout's own remote and current branch.

New props: source ('clone' | 'local'), hideSourceSelect, prefilledRepoDir (setting it starts the block on the local source).

Notable implementation points

  • git:local-repo has a register flag. The live preview passes register: false; only the user confirming registers the worktree and resolves the GitHub numeric IDs. A half-typed path never grants anything.
  • resolveValidatedWorktree now accepts already-registered worktrees (electron/main/ipc/workspace.ts). Without this, workspace:register / workspace:set-active silently rejected any checkout outside the session working directory — which is exactly where local checkouts live — so the active-worktree selection didn't stick and REPO_FILES could point at the wrong repo. This does not widen the grant: an unregistered path outside the session still fails. The user's explicit selection is what grants access.
  • Auth is only required for cloning. Selecting files already on disk waits on nothing; the clone form still gates on a linked auth block as before.
  • A checkout with no origin is still selectable, with an inline warning that PR blocks need a remote. A repo with no commits works too.
  • Instruction mode renders cd <path> rather than a git clone command.
  • Test framework support: the runbook test CLI adopts a checkout for source="local" instead of cloning, counting tracked files rather than walking .git.

Testing

  • 11 domain tests for inspectLocalRepo — subdirectory → root resolution, relative vs absolute display paths, no remote, no commits, and each failure mode (missing dir, a file, not a work tree, empty input).
  • 12 component tests driving the real useGitClone against a mocked IPC boundary: source switching, prefill behaviour, the preview not registering, the confirm registering the worktree with the right owner/ref, the native folder picker, and the no-remote warning.
  • 2 instruction-mode tests, 2 CLI executor tests against a real git init fixture.

992 backend + 604 web tests pass; typecheck, lint, and just test-docs clean.

Not verified in the desktop app — the UI is covered by component tests only, no live Electron run.

🤖 Generated with Claude Code

<GitClone> now has a repository-source picker: clone from a remote (unchanged)
or point at a checkout the user already has on disk. Users often have the repo
already — a long-lived infrastructure-live checkout, a work in progress branch,
a monorepo they don't want to re-download.

Picking a directory inspects it without touching it: resolve the work tree root
via `git rev-parse --show-toplevel` (so any subdirectory of the checkout works),
read the origin remote and current branch, count tracked files. That runs as the
user types or browses, so a wrong directory says so immediately. Confirming with
"Use This Repo" registers the checkout as a session worktree and emits the same
outputs a clone does, so nothing downstream can tell the two apart: same
clone_path/repo_owner/repo_name, same $REPO_FILES, same workspace file tree,
same <GitPullRequest> flow (opening against the checkout's own remote and
current branch).

Backend:
- src/domain/git/local-repo.ts: inspectLocalRepo() — root resolution, remote/ref
  metadata, tracked-file count, and typed user-facing failures for a missing
  directory, a file, or a directory that isn't a git work tree. A repo with no
  commits is still selectable.
- GitClient.getRepoRoot() added to the service, the CLI layer, and the test stub.
- git:local-repo IPC handler. The live preview passes register:false; only the
  user confirming registers the worktree and resolves GitHub numeric IDs. That
  split keeps a half-typed path from granting anything.
- workspace.ts: resolveValidatedWorktree() now accepts already-registered
  worktrees. Without this, workspace:register / workspace:set-active silently
  rejected any checkout outside the session working directory — which is where
  local checkouts normally live — so the active-worktree selection didn't stick
  and REPO_FILES could point at the wrong repo. It does not widen the grant:
  an unregistered path outside the session still fails.

Frontend: SourceSelect (styled after GitAuth's ProviderSelect), LocalRepoForm
with a native folder picker, and source-aware copy in the result panel. New
props: source ('clone' | 'local'), hideSourceSelect, prefilledRepoDir — the last
one starts the block on the local source. Selecting a checkout requires no
credentials; only cloning still waits on a linked auth block. Instruction mode
renders `cd <path>` instead of a git clone command.

The runbook test framework adopts a checkout for source="local" rather than
cloning, counting tracked files instead of walking .git.

Tests: 11 domain tests for inspectLocalRepo, 12 component tests driving the real
hook against a mocked IPC boundary, 2 instruction-mode tests, and 2 CLI executor
tests against a real `git init` fixture. Docs cover the new source, props, and
output behaviour.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@odgrim
odgrim requested a review from josh-padnick as a code owner August 21, 2026 10:52
@vercel

vercel Bot commented Aug 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
runbooks Ready Ready Preview Aug 21, 2026 10:52am

Request Review

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Your included review limit has been reached.

You’re in a promotional period — use the checkbox below to run this review for free:

  • Run review for free

On-demand reviews are free for the next 30 days. After that, they cost $0.25 per reviewed file.

How can I continue?

Run this review now using the option above, or comment @coderabbitai review --use-credits.

You can also wait for the limit to reset (next review available in 59 seconds), then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cf98951d-b99a-4e7e-ad3a-169632738ccc

📥 Commits

Reviewing files that changed from the base of the PR and between d3ac06e and 8513f86.

📒 Files selected for processing (23)
  • cli/test/executor.test.ts
  • cli/test/executor.ts
  • docs/src/content/docs/authoring/blocks/GitClone.mdx
  • electron/main/ipc/git.ts
  • electron/main/ipc/workspace.ts
  • electron/preload/index.ts
  • electron/shared/channels.ts
  • src/domain/git/local-repo.test.ts
  • src/domain/git/local-repo.ts
  • src/layers/GitCliClient.ts
  • src/services/GitClient.ts
  • src/test-utils/TestLayer.ts
  • web/src/components/mdx/GitClone/GitClone.tsx
  • web/src/components/mdx/GitClone/GitCloneInstruction.tsx
  • web/src/components/mdx/GitClone/__tests__/GitClone.instruction.test.tsx
  • web/src/components/mdx/GitClone/__tests__/GitClone.local.test.tsx
  • web/src/components/mdx/GitClone/components/CloneResult.tsx
  • web/src/components/mdx/GitClone/components/LocalRepoForm.tsx
  • web/src/components/mdx/GitClone/components/SourceSelect.tsx
  • web/src/components/mdx/GitClone/hooks/useGitClone.ts
  • web/src/components/mdx/GitClone/index.ts
  • web/src/components/mdx/GitClone/types.ts
  • web/src/components/mdx/GitClone/utils.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@odgrim
odgrim merged commit bfb2476 into main Aug 21, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant